package com.aocore.proxy;

import com.aocore.AoCoreProperties;
import com.aocore.awesomo.AwesomO;
import com.aocore.packet.CC.BnetAuthRequest;
import com.aocore.packet.CCPacket;
import com.aocore.packet.CS.BnetAuthResponse;
import com.aocore.packet.CS.BnetConnectionResponse;
import com.aocore.packet.CS.RealmLogonResponse;
import com.aocore.packet.CSPacket;
import com.aocore.packet.Packet;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author derek
 */
public final class ChatProxy extends Proxy
{
    private boolean magic = true;
    private int serverToken;

    public ChatProxy(SocketChannel socketChannel) throws IOException
    {
        super(socketChannel);
        System.out.println("NEW CHAT PROXY");
        connectClient(new InetSocketAddress(AoCoreProperties.REALM, AoCoreProperties.CHAT_PORT));
    }

    public void writePacket(CSPacket packet) throws IOException
    {
        writeServerPacket(packet);
    }

    public void writePacket(CCPacket packet) throws IOException
    {
        writeClientPacket(packet);
    }

    @Override
    protected List<Packet> parseClientPacket(ByteBuffer byteBuffer)
    {
        List<Packet> packets = new LinkedList<Packet>();

        while (true)
        {
            if (magic)
            {
                byte[] data = new byte[1];

                byteBuffer.flip();
                byteBuffer.get(data);
                byteBuffer.compact();

                Packet packet = new com.aocore.packet.CC.Invalid(data);
                packets.add(packet);

                magic = false;
                continue;
            }

            if (byteBuffer.get(0) != (byte)0xFF)
            {
                byte[] data = new byte[byteBuffer.position()];

                byteBuffer.flip();
                byteBuffer.get(data);
                byteBuffer.compact();

                Packet packet = new com.aocore.packet.CC.Invalid(data);
                packets.add(packet);

                break;
            }

            if (byteBuffer.position() < 4)
            {
                break;
            }

            int packet_length = byteBuffer.getShort(2);

            if (packet_length > byteBuffer.position())
            {
                break;
            }

            byte[] data = new byte[packet_length];

            byteBuffer.flip();
            byteBuffer.get(data);
            byteBuffer.compact();

            Packet packet = CCPacket.create(data);
            packets.add(packet);
        }

        return packets;
    }

    @Override
    protected List<Packet> parseServerPacket(ByteBuffer byteBuffer)
    {
        List<Packet> packets = new LinkedList<Packet>();

        while (true)
        {
            if (byteBuffer.position() < 4)
            {
                break;
            }

            if (byteBuffer.get(0) != (byte)0xFF)
            {
                byte[] data = new byte[byteBuffer.position()];

                byteBuffer.flip();
                byteBuffer.get(data);
                byteBuffer.compact();

                Packet packet = new com.aocore.packet.CS.Invalid(data);
                packets.add(packet);

                break;
            }

            int packet_length = byteBuffer.getShort(2);

            if (packet_length > byteBuffer.position())
            {
                break;
            }

            byte[] data = new byte[packet_length];

            byteBuffer.flip();
            byteBuffer.get(data);
            byteBuffer.compact();

            Packet packet = CSPacket.create(data);
            packets.add(packet);
        }

        return packets;
    }

    @Override
    protected Packet processClientPacket(Packet packet)
    {
        if (packet instanceof BnetAuthRequest)
        {
            BnetAuthRequest bnetAuthRequest = (BnetAuthRequest) packet;
            bnetAuthRequest.setCdKey(serverToken, "CKGX2W7REPHHG72K");
        }

        return packet;
    }

    @Override
    protected Packet processServerPacket(Packet packet)
    {
        if (packet instanceof BnetAuthResponse)
        {
            awesomO = new AwesomO();
            awesomO.setChatProxy(this);
            awesomO.start();
        }
        if (packet instanceof BnetConnectionResponse)
        {
            BnetConnectionResponse bnetConnectionResponse = (BnetConnectionResponse) packet;
            serverToken = bnetConnectionResponse.getServerToken();
        }
        else if (packet instanceof RealmLogonResponse)
        {
            RealmLogonResponse realmLogonResponse = (RealmLogonResponse) packet;

            try
            {
                InetSocketAddress address = new InetSocketAddress(InetAddress.getByAddress(realmLogonResponse.getIp()), (int) realmLogonResponse.getPort());
                awesomO.setRealmAddress(address);
                bots.put(Arrays.hashCode(realmLogonResponse.getHash()), awesomO);
            }
            catch (UnknownHostException e)
            {
                e.printStackTrace(System.err);
                stopProxy();
            }
        }

        return packet;
    }
}
